package ccnGame;


/**
 * A Baseball game program.
 * 
 * written by Gihoon Kim.
 * 
 * 
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import ccnGame.CCNGameNet.CCNGameCallBack;
import org.ccnx.ccn.config.ConfigurationException;
import org.ccnx.ccn.io.content.ContentEncodingException;
import org.ccnx.ccn.protocol.MalformedContentNameStringException;


public class BaseballGame extends JFrame implements ActionListener, CCNGameCallBack{
	private static final long serialVersionUID = -8779269133035264361L;
	
	private char _number[] = new char[3];
	
	//game window
	protected JTextArea  _messageArea= new JTextArea(10, 32);
	private JTextField  _textField= new JTextField(32);
	private int cnt=0;
	private int certification = 0;  // 0: can't play  1: can play
	private int playing = 0; // 0: not playing  1: playing
	private int input =0; //0:input 1:one person input 2: two people input
	
	private String player[] = new String[2];
	private String _current;
	private String nickname;
	private Iterator<String> _userlist;
	
	private final CCNGameNet _game;
	
	public BaseballGame(String namespace, String nick) throws MalformedContentNameStringException {
		nickname = nick;
		_game = new CCNGameNet(this, namespace, nickname);
				
		addWindowListener(
		           new WindowAdapter() {
		               public void windowClosing(WindowEvent e) {
		                   try {
							stop();
						} catch (IOException e1) {
							System.out.println("IOException shutting down listener: " + e1);
							e1.printStackTrace();
						}
		               }
		          }
	    );
		
		//make window
		_messageArea.setEditable(false);
		_messageArea.setBackground(Color.LIGHT_GRAY);
		_messageArea.setLineWrap(true);
		_textField.addActionListener(this);
		
		Container content = getContentPane();
		content.add(new JScrollPane(_messageArea), BorderLayout.CENTER);
		content.add(_textField, BorderLayout.SOUTH);
		
		//display the window
		setTitle("Baseball game: ["+namespace+"]");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		_textField.requestFocusInWindow();
	}
	
	/**
	 * Process input to textfield.
	 */
	public void actionPerformed(ActionEvent e) {
		try{
			String newText = _textField.getText();
			if((null != newText) && (newText.length() >0)){
				if(playing==1){
					if(cnt==0){
						if(newText.length()!=3){
							recvMessage("You should type 3 numbers.\n");
						}
						else if(checkNumber(newText)==-1){
							recvMessage("each number has to be different.\n");
						}else{
							setNumber(newText);
							_game.sendMessage("System:::: "+nickname+" type 3 numbers.");
							cnt++;
						}
					}else{
						if(certification==2 && input<2){
							recvMessage("Waiting.... all player should type the number.\n");
						}else{
							if(_current.compareTo(nickname) ==0){
								if(newText.length()!=3 ){
									recvMessage("You should type 3 numbers. \n");
								}else{
									_game.sendMessage(newText);
								}
							}
							else{
								recvMessage("Not you're turn\n");
							}
						}
					}
				}
				else{
					recvMessage("You're not playing now\n");
				}

			}
		}
		catch(Exception e1){
			System.err.println("Exception input : "+e1.getClass().getName()+": "+e1.getMessage());
			e1.printStackTrace();
			recvMessage("Exception input : " + e1.getClass().getName()+": "+e1.getMessage());
		}
		_textField.setText("");
		_textField.requestFocusInWindow();
	}
	
	/**
	 * Add a message to the output
	 * @param message
	 */
	public void recvMessage(String message){
		_messageArea.insert(message, _messageArea.getText().length());
		_messageArea.setCaretPosition(_messageArea.getText().length());
	}
	
	public void recvMessage(Message m1){
		String sender = m1.getName();
		String msg = m1.getMsg();
		String result;
		
		result = "["+sender+"] "+msg;
		
		if(m1.getState()==Message.LOGIN_MESSAGE){
			recvMessage(msg+"\n");
			if(playing==0 && _game.numberOfUser()>2){
				recvMessage("game already starts. \n");
			}else if(_game.numberOfUser()==1||_game.numberOfUser()==2){
				restart();
			}else{
				
			}
		}
		else if(m1.getState() == Message.SYSTEM_MESSAGE){
			recvMessage(result+"\n");
			
			if(msg.compareTo("Correct")==0){
				restart();
			}else{
				input++;
				if(certification==2 && input>=2){
					//_current = player[input/2];
					/*if(certification==1){
						_current = player[0];
					}
					else*/ 
					_current = player[input%2];
					recvMessage(" -- "+_current+" turn -- \n");
				}else if(certification==1){
					_current = player[0];
					recvMessage(" -- "+_current+" turn -- \n");
				}else{
					
				}
			}
		}else if(m1.getState()==Message.SHUTDOWN_MESSAGE){
			if(sender.compareTo(player[0])==0 || sender.compareTo(player[1])==0){
				restart();
			}
		}
		else{
			
			recvMessage(result+"\n");
			if(playing==1 && (certification==1 ||(certification==2 &&sender.compareTo(nickname)!=0))){
				try {
					_game.sendMessage("System::::"+compareProcess(msg));
				} catch (ContentEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}			
	}
	
	public void restart(){
		playing=0;
		certification =0;
		cnt=0;
		input=0;
		
		if(_game.numberOfUser() ==1 ){ 
			_userlist = _game.getUserList();
			_current = _userlist.next();
			player[0] = _current;
			certification=1;
		}else if(_game.numberOfUser()>=2){
			_userlist = _game.getUserList();
			player[0] = _userlist.next();
			player[1] = _userlist.next();
			if(nickname.compareTo(player[0])==0 || nickname.compareTo(player[1])==0)
				certification=2;
		}
		if(certification==1 || certification==2){
			playing=1;
			recvMessage(" START NEW GAME \n Input 3 numbers.\n");
		}
	}
	public int checkNumber(String s){
		if(s.charAt(0)==s.charAt(1)) return -1;
		else if(s.charAt(1)==s.charAt(2)) return -1;
		else if(s.charAt(0) == s.charAt(2)) return -1;
		else return 0;
	}
	public String compareProcess(String m1){
		char[] _num = getNumberchar();
		int strike =0;
		int ball=0;
		String result;
		
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				if(m1.charAt(i) == _num[j]){
					if(i==j){
						strike++;
					}
					else ball++;
				}
			}
		}
		
		if(strike ==3) result = "Correct";
		else result = "strike : "+strike+" ball : "+ball ;
		
		return result;
	}
	
	public void setNumber(String n){
		for(int i=0; i<3; i++){
			_number[i] = n.charAt(i);
		}
	}
	public String getNumber(){
		String result = "" + _number[0] + _number[1] + _number[2];
		return result;
	}
	public char[] getNumberchar(){
		return _number;
	}
	
	public static void usage(){
		System.err.println("usage : BaseballGame <ccn URl>");	
	}
	
	/**
	 * Called by window thread when window is closed.
	 */
	protected void stop() throws IOException{
		_game.shutDown();
	}
	
	/**
	 * This blocks until _game.shutdown() called
	 * @throws IOException 
	 * @throws MalformedContentNameStringException 
	 * @throws ConfigurationException 
	 */
	protected void start() throws ConfigurationException, MalformedContentNameStringException, IOException {
		_game.connect();
	}
	
}
